#!/usr/bin/env python3

import os
import configure_semantic_segment
from common_functions import ReadFromFile

keyboard_exceptions_root = configure_semantic_segment.parser_exceptions_root
keyboard_exception_list = ReadFromFile(os.path.join(keyboard_exceptions_root, 'keyboard_exceptions.txt'))

def find_keyboard_row_column(char):
    row1=['1','2','3','4','5','6','7','8','9','0','-','=']
    s_row1=['!','@','#','$','%','^','&','*','(',')','_','+']

    row2=['q','w','e','r','t','y','u','i','o','p','[',']','\\']
    s_row2=['Q','W','E','R','T','Y','U','I','O','P','{','}','|']

    row3=['a','s','d','f','g','h','j','k','l',';','\'']
    s_row3=['A','S','D','F','G','H','J','K','L',':','"']

    row4=['z','x','c','v','b','n','m',',','.','/']
    s_row4=['Z','X','C','V','B','N','M','<','>','?']

    if char in row1:
        return (0,row1.index(char))
    if char in s_row1:
        return (0,s_row1.index(char))
    if char in row2:
        return (1,row2.index(char))
    if char in s_row2:
        return (1,s_row2.index(char))
    if char in row3:
        return (2,row3.index(char))
    if char in s_row3:
        return (2,s_row3.index(char))
    if char in row4:
        return (3,row4.index(char))
    if char in s_row4:
        return (3,s_row4.index(char))

    return None

def _is_next_on_keyboard(past, current):
    if (past == None) or (current == None):
        return False
    if (current[0] == past[0]) and (current[1] == past[1]):
        return False
    if (current[0] == past[0]):
        if (current[1] == past[1]) or (current[1] == past[1]-1) or (current[1] == past[1]+1):
            return True
    elif (current[0] == past[0]+1):
        if (current[1] == past[1]) or (current[1] == past[1]-1):
            return True
    elif (current[0] == past[0]-1):
        if (current[1] == past[1]) or (current[1] == past[1]+1):
            return True

    return False

def _interesting_keyboard(combo):
    if len(combo) < 3:
        return False
    if (combo[0] == 'e'):
        return False
    if (combo[1] == 'e') and (combo[2] == 'r'):
        return False
    if (combo[0] == 't') and (combo[1] == 'y'):
        return False
    if (combo[0] == 't') and (combo[1] == 't') and (combo[2] == 'y'):
        return False
    if (combo[0] == 'y'):
        return False

    '''
    false_positive_words = [
        "drew",
        "kiki",
        "fred",
        "were",
        "pop",
    ]
    '''
    full_lower_word = ''.join(combo).lower()

    for item in keyboard_exception_list:
        if item in full_lower_word:
            return False
    alpha = 0
    special = 0
    digit = 0
    for c in combo:
        if c.isalpha():
            alpha=1
        elif c.isdigit():
            digit=1
        else:
            special=1

    if (alpha + special + digit) >=2 or alpha == 1 or special == 1:                                                                                                       return True
    return False

def _inner_keyboard_detect(password, min_keyboard_run = 4):
    past_pos = None
    cur_combo = []
    section_list = []

    for index, x in enumerate(password):
        pos = find_keyboard_row_column(x)
        is_run = _is_next_on_keyboard(past_pos, pos)
        if is_run == True:
            cur_combo.append(x)
        else:
            if len(cur_combo) >= min_keyboard_run:
                if _interesting_keyboard(cur_combo):
                    if len(cur_combo) != index:
                        section_list.append((password[0:index-len(cur_combo)],None))
                    section_list.append((''.join(cur_combo),"KB"+str(len(cur_combo)) ))
                    if index != (len(password)):
                        temp_section = _inner_keyboard_detect(password[index:])
                        section_list.extend(temp_section)
                        return section_list
            cur_combo = [x]
        past_pos = pos

    if len(cur_combo) >= min_keyboard_run:
        if _interesting_keyboard(cur_combo):
            if len(cur_combo) != len(password):
                section_list.append((password[0:len(password)-len(cur_combo)],None))
            section_list.append((''.join(cur_combo),"KB"+str(len(cur_combo))))
        else:
            section_list.append((password,None))
    else:
        section_list.append((password,None))

    return section_list

def keyboard_detect(segmentList):
    result_list = []
    for segItem in segmentList:
        if segItem[1] == None:
            keyboard_detect_list = _inner_keyboard_detect(segItem[0])
            for item in keyboard_detect_list:
                result_list.append(item)
        else:
            result_list.append(segItem)
    return result_list

if __name__ == '__main__':
    section_list = keyboard_detect([('awesome', None)])
    print(section_list)
